#!/usr/bin/env ruby

require 'thread'
require 'monitor'

require 'simmon/logging'

module Simmon
  # An extremely simple/minimalistic asynchronous mailbox. A mailbox
  # has a certain maximum size. Delivering items to the mailbox is
  # guaranteed not to block. The trade-off is that if the mailbox
  # becomes full (because delivered objects are not consumed fast
  # enough), items are lost.
  class Mailbox
    attr_reader :name

    # Initialize a mailbox with the given name and maximum size.
    def initialize(name, size = 1000)
      @name = name
      @maxsize  = size
      
      @items    = [] # todo/xxx: this should seriously be a linked list or other O(1) structure
      @monitor  = Monitor.new()
      @put_cond = @monitor.new_cond()

      @log = Log4r::Logger['simmon']
    end

    # Get the next entry to the mailbox, in a blocking fashion.
    def get()
      @monitor.synchronize() do
        while @items.empty?() do
          @put_cond.wait()
        end

        @items.shift()
      end
    end

    # Deliver an object to the mailbox (if there is room).
    def put(object)
      @monitor.synchronize() do
        if @items.size() < @maxsize then
          @items.push(object)
          @put_cond.signal()
        else
          @log.warn("mailbox full - dropping object")
        end
      end
    end
  end
end
